{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 地址与指针\n",
    "\n",
    "```{admonition} 需求\n",
    "简单理解地址与指针的概念。\n",
    "```\n",
    "\n",
    "```{hint}\n",
    "{guilabel}`视频`\n",
    "\n",
    "...\n",
    "```\n",
    "\n",
    "在内存中保存的任何东西都有一个 **地址**。例如：\n",
    "\n",
    "```cpp\n",
    "int var = 17;\n",
    "```\n",
    "\n",
    "这段代码为变量 `var` 分配一段 “int 大小” 的内存，并将值 `17` 保存到这段内存中。\n",
    "\n",
    "可以保存和操作地址。保存地址的对象（即一块内存或者说是一个内存字节序列）被称为 **指针**。例如，用于保存 `int` 的地址的类型称为“指向 `int` 的指针”或“`int` 指针”，其表示方法为 `int*`：\n",
    "\n",
    "```cpp\n",
    "int* ptr = &var // ptr 保存 var 的地址\n",
    "```\n",
    "\n",
    "地址运算符 `&` 用于获得一个对象的地址。\n",
    "\n",
    "每种类型都有对应的指针类型。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "@0x7fff19cd14f8"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int x = 17;\n",
    "\n",
    "int* pi = &x; // int 指针\n",
    "pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "@0x7fff19cd14f8"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "double e = 2.14143;\n",
    "\n",
    "double* pd = &e; // double 指针\n",
    "pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "查看指向的对象的值，可以使用 “内容”运算符 `*` （这是一元运算符）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "17"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.1414300"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**内容运算符** （常称为 **解引用** 运算符）也可以被用于赋值操作的左侧："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "27.000000"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "*pi = 27; // 正确：可以将 27 赋予 pi 指向的 int\n",
    "*pd = 3.14; // 正确：可以将 3.14 赋予 pd 指向的 double\n",
    "*pd = *pi; // 正确：可以将一个 int (*pi) 赋予一个 double (*pd)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{important}\n",
    "- 指针类型提供一些适用于地址的操作；\n",
    "- `int` 提供适用于整数的（算术和逻辑）操作。\n",
    "```\n",
    "\n",
    "````{warning}\n",
    "不要混用指针和整数！\n",
    "\n",
    "```cpp\n",
    "int i = pi; // 错误：不能将一个 int* 赋予一个 int\n",
    "pi = 7; // 错误：不能将一个 int 赋予一个 int*\n",
    "```\n",
    "````\n",
    "\n",
    "同样，不同类型的指针也不能混用：\n",
    "\n",
    "```cpp\n",
    "char* pc = pi; // 错误：不能将一个 int* 赋予一个 chat*\n",
    "\n",
    "char c = 'a';\n",
    "char* pc = &c;\n",
    "pi = pc; // 错误：不能将一个 char* 赋予一个 int*\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++11",
   "language": "C++11",
   "name": "python3100jvsc74a57bd0a2954483fe4136a94bd721da8601251ae4c667fedb6adcfe70ff0183b19bacbc"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++11",
   "version": "11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
